#include "testing/testing.hpp"

#include "tbcore/pch.hpp"

#include "rocksdb.hpp"

struct RocksdbTest : public ::testing::Test {
	virtual void SetUp() {
		TB_NAMESPACE::Result res = db.OpenDB(_T("test_db"));
		ASSERT_TRUE(res);
	}

	virtual void TearDown() {
		db.CloseDB();
	}

	TB_NAMESPACE::RocksDB db;
};

TEST_F(RocksdbTest, BasicOps) {
	using namespace TB_NAMESPACE;

	uint32 u32 = 123;
	Result res = db.Write("test_u32", (char*)(&u32), sizeof(u32));
	EXPECT_TRUE(res);

	uint32* ru32 = nullptr;
	uint32 len;
	res = db.Read("test_u32", (char**)(&ru32), len);
	EXPECT_TRUE(res);

	EXPECT_EQ(u32, *ru32);

	res = db.Delete("test_u32");
	EXPECT_TRUE(res);

	ru32 = nullptr;
	len = 0;
	res = db.Read("test_u32", (char**)(&ru32), len);
	EXPECT_TRUE(res);
	EXPECT_EQ(len, 0);
}

TEST_F(RocksdbTest, ReadByUpperBound) {
  using namespace TB_NAMESPACE;

  uint32 u32 = 123;

  ASSERT_TRUE(db.Write("test_u32_1", (char*)(&u32), sizeof(u32)));
  ASSERT_TRUE(db.Write("test_u32_2", (char*)(&u32), sizeof(u32)));
  ASSERT_TRUE(db.Write("test_u32_3", (char*)(&u32), sizeof(u32)));

  DBIteratorPtr it = db.ReadByRange("test_u32_1", "test_u32_3");
  const char* key = nullptr;
  std::size_t keylen;
  const char* val = nullptr;
  std::size_t vallen;
  for (int i = 0; i < 2; ++i) {
    Result r = it->Next(&key, keylen, &val, vallen);
    ASSERT_TRUE(r);
  }
}

REGISTER_STD_VECTOR(double);

TEST_F(RocksdbTest, VariantOps) {
	using namespace TB_NAMESPACE;

	std::vector<double> a(10, 1.23);
	Variant v = Variant::FromValue(a);

	Result res = db.WriteValue("test_variant_arr", v);
	EXPECT_TRUE(res);

	Variant rv;
	res = db.ReadValue("test_variant_arr", rv);
	EXPECT_TRUE(res);
	EXPECT_EQ(rv.Value<std::vector<double> >(), a);
}